package net.alche.fa.core.parse;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.hutool.core.util.ArrayUtil;
import net.alche.al.util.AC;
import net.alche.al.util.M;
import net.alche.fa.core.model.Logic;

public class FavaParseUtil {
  public static final String[] keywords = new String[] { "if", "else", "else if", "for", "switch", "return", "public",
      "private", "class",
      "new", "default", "break", "continue", "try", "catch", "throws", "throw", "static",
      "protected", "interface", "enum", "abstract", "while", "case", "extends", "final", "instanceof", "implements",
      "native", "transient", "synchronized", "super", "package", "assert" };
  public static final String[] keySymbolJava = new String[] { "{", "}", "[", "]", "(", ")", "+", "-", "*", "/", "%",
      "=", ">", "<",
      "!",
      ".", "?", ":", "&", "|", ",", ";", "@", "#", "\"", "'", "^", "\\", "`" };
  public static final String[] doubleSymbolJava = new String[] { ">=", "<=", "!=", "==", "&&", "||", "++", "--", "=>",
      "{}", "@@",
      "[]",
      "+=", "-=", "*=", "->", "/=", "%=", "...", ">>", "<<" };
  // 运算级别
  public static final String[] priority0 = new String[] { "()", "(", ")", "{", "[" };
  public static final String[] priority1 = new String[] { "." };
  public static final String[] priority2 = new String[] { "++", "--", "!", "var" };
  public static final String[] priority3 = new String[] { "*", "/", "%" };
  public static final String[] priority4 = new String[] { "+", "-" };

  public static final String[] priority5 = new String[] { "<", "<=", ">", "=>", "==", "!=" };
  public static final String[] priority6 = new String[] { "&&" };
  public static final String[] priority7 = new String[] { "||" };
  public static final String[] priority11 = new String[] { ":" };
  public static final String[] priority12 = new String[] { "?", "new" };

  public static final String[] priority13 = new String[] { "=", "+=", "-=", "*=", "/=", "%=" };
  public static final String[] priority14 = new String[] { "try", "return", "break", "continue", "catch" };

  public static boolean isJav(String str) {
    return ArrayUtil.contains(keywords, str) || ArrayUtil.contains(keySymbolJava, str)
        || ArrayUtil.contains(doubleSymbolJava, str);
  }

  public static Map<String, String> getAttrs(String line) {
    Map<String, String> attrMp = new HashMap<>();
    line = line.replaceAll("\"  \"", "\"^+2+^\"");
    line = line.replaceAll("\" \"", "\"^+1+^\"");
    String[] sp = line.split(" ");
    for (int i = 0; i < sp.length; i++) {
      String item = sp[i];
      if (i == 0)
        continue;
      if (item.equals("=")) {
        String val = sp[i + 1];
        if (val.startsWith("\"") && val.endsWith("\"")) {
          val = val.substring(1, val.length() - 1);
          if (val.equals("^+2+^")) {
            val = "  ";
          }
          if (val.equals("^+1+^")) {
            val = " ";
          }
        }
        attrMp.put(sp[i - 1], val);
      } else {
        continue;
      }
    }
    return attrMp;
  }

  public static Logic getLogic(String coder) {
    Logic lg = new Logic();
    String[] wrds = coder.split(" ");
    List<Logic> ls = new ArrayList<>();
    for (int i = 0; i < wrds.length; i++) {
      if (AC.empty(wrds[i]))
        continue;
      Logic item = new Logic();
      if (isJav(wrds[i])) {
        item.setWhat(wrds[i]);
      } else {
        item.setObj(wrds[i]);
      }
      ls.add(item);
    }
    getLogicFold(lg, ls, false);
    lg = lg.getLogicObj();
    return lg;
  }

  // 折叠优先级
  static void getLogicFold(Logic par, List<Logic> lgs, boolean isData) {
    Logic first = lgs.get(0);
    if (first == null)
      return;
    int okIndex = -1;
    Logic okLogic = null;
    int operValue = -1; // 运算级别
    for (int i = 0; i < lgs.size(); i++) {
      Logic lg = lgs.get(i);
      if (AC.notEmpty(lg.getWhat())) {
        int val = getOperPriority(lg.getWhat());
        if (val >= operValue) {
          operValue = val;
          okIndex = i;
          okLogic = lg;
        }
      }
    }
    boolean isSingle = false;
    if (lgs.size() == 1) {
      okLogic = lgs.get(0);
      okIndex = 0;
      isSingle = true;
    }
    if (okLogic != null) {
      List<Logic> objs = new ArrayList<>();
      List<Logic> datas = new ArrayList<>();
      for (int i = 0; i < lgs.size(); i++) {
        Logic item = lgs.get(i);
        if (i < okIndex) {
          objs.add(item);
        } else if (i > okIndex) {
          datas.add(item);
        }
      }
      if (isData) {
        if (isSingle && AC.empty(okLogic.getWhat()))
          par.setData(okLogic.getObj());
        else
          par.setLogicData(okLogic);
      } else {
        if (isSingle && AC.empty(okLogic.getWhat()))
          par.setObj(okLogic.getObj());
        else
          par.setLogicObj(okLogic);
      }
      if (!AC.empty(objs))
        getLogicFold(okLogic, objs, false);
      if ("new".equals(okLogic.getWhat()))
        getLogicFold(okLogic, datas, false);
      else if (!AC.empty(datas))
        getLogicFold(okLogic, datas, okIndex != 0);
      if (!AC.empty(okLogic.getChild()) || "(".equals(okLogic.getWhat())) {
        if ("(".equals(okLogic.getWhat())
            && (par.getWhat() == null || M.contain(new String[] { ".", "new" }, par.getWhat()))) {

        } else if ("(".equals(okLogic.getWhat()) && okLogic.getObj() != null) { // && $osJava.findMethod(this.anaClass,
                                                                                // okLogic.obj , null , true, true)
        } else if (!AC.empty(okLogic.getChild())) {
          Logic nextPar = okLogic;
          getLogicFold(nextPar, okLogic.getChild(), M.contain(new String[] { "(", "{", "[" }, okLogic.getWhat()));
        }
        okLogic.setChild(null);
        // delete okLogic.child
      }
    }
  }

  // 运算级别
  public static int getOperPriority(String operWord) {
    if (AC.empty(operWord))
      return 101;
    if (operWord.startsWith("var-"))
      return 5;
    if (operWord.startsWith("fm-sta"))
      return 5;
    if (operWord.startsWith("fa-"))
      return 90;
    if (M.contain(priority0, operWord))
      return 0;
    if (M.contain(priority1, operWord))
      return 5;
    if (M.contain(priority2, operWord))
      return 15;
    if (M.contain(priority3, operWord))
      return 20;
    if (M.contain(priority4, operWord))
      return 25;
    if (M.contain(priority5, operWord))
      return 30;
    if (M.contain(priority6, operWord))
      return 35;
    if (M.contain(priority7, operWord))
      return 40;
    if (M.contain(priority11, operWord))
      return 45;
    if (M.contain(priority12, operWord))
      return 50;
    if (M.contain(priority13, operWord))
      return 55;
    if (M.contain(priority14, operWord))
      return 60;
    return 100;
  }
}
